#include<iostream>
using namespace std;


//// 使用RAII思想设计的SmartPtr类---利用生命周期来控制程序资源
//template<class T>
//class SmartPtr {
//public:
//    SmartPtr(T* ptr = nullptr)// 在对象构造时获取资源
//        : _ptr(ptr)
//    {}
//
//    ~SmartPtr() // 最后在对象析构的时候释放资源
//    {
//        if (_ptr)
//            delete _ptr;
//    }
//
//    T& operator*() { return *_ptr; }
//    T* operator->() { return _ptr; }
//
//private:
//    T* _ptr;
//};
//
//int div()
//{
//    int a, b;
//    cin >> a >> b;
//    if (b == 0)
//        throw invalid_argument("除0错误");
//    return a / b;
//}
//
//void Func()
//{
//    SmartPtr<int> sp1(new int);
//    SmartPtr<int> sp2(new int);
//    cout << div() << endl;
//}
//
//// 好处：
//// 不需要显式地释放资源
//// 采用这种方式，对象所需的资源在其生命期内始终保持有效
//
////int main()
////{
////    try
////    {
////        Func();
////    }
////    catch (const exception& e)
////    {
////        cout << e.what() << endl;
////    }
////    return 0;
////}
//
//struct Date
//{
//    int _year;
//    int _month;
//    int _day;
//};
//
//int main()
//{
//    SmartPtr<int> sp1(new int);
//    *sp1 = 10;
//        cout << *sp1 << endl;
//
//    SmartPtr<Date> sparray(new Date);
//    // 需要注意的是这里应该是sparray.operator->()->_year = 2018;
//    // 本来应该是sparray->->_year这里语法上为了可读性，省略了一个->
//    sparray->_year = 2018;
//    sparray->_month = 1;
//    sparray->_day = 1;
//}


// auto_ptr -- 管理权限转移
//template<class T>
//class SmartPtr {
//public:
//	SmartPtr(T* ptr = nullptr)
//		: _ptr(ptr)
//	{}
//	~SmartPtr()
//	{
//		if (_ptr)
//			delete _ptr;
//	}
//	T& operator*() { return *_ptr; }
//	T* operator->() { return _ptr; }
//private:
//	T* _ptr;
//};
//
struct Date
{
	int _year;
	int _month;
	int _day;

	Date(int year = 1, int month = 1, int day = 1)
		:_year(year)
		, _month(month)
		, _day(day)
	{}

	~Date()
	{
		cout << "~Date()" << endl;
	}
};
//
//int main()
//{
//	//SmartPtr<Date> sp1(new Date);
//	//SmartPtr<Date> sp2(sp1);//浅拷贝/值拷贝（sp1、sp2指向同一块空间，析构两次，导致程序错误）
//
//	auto_ptr<Date> ap1(new Date);
//	// 拷贝时，管理权限转移，被拷贝(ap1)悬空
//	auto_ptr<Date> ap2(ap1);
//
//	ap1->_year++;
//
//	return 0;
//}


template<class T>
class DeleteArray
{
public:
	void operator()(T* ptr)
	{
		delete[] ptr;
	}
};

class Fclose
{
public:
	void operator()(FILE* ptr1)
	{
		cout << "fclose:" << ptr1 << endl;
		Fclose(ptr);
	}
};

int main()
{
	// C++11
	unique_ptr<Date> up1(new Date);

	// 不支持拷贝(拷贝会被悬空)
	//auto_ptr<Date> up2(up1);

	//定制删除器
	//unique_ptr<Date, DeleteArray<Date>> up2(new Date[5]);// delete[] 不匹配，要单独写
	unique_ptr<Date[]> up2(new Date[5]);//调用特化版本
	unique_ptr<FILE, Fclose> up3(fopen("test.cpp", "r"));
}